use core::ops::Add;
use core::ops::Sub;

use crate::vm::pgtable::page;

use super::pfnaddr::Pfnaddr;

/// 物理地址结构定义
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Paddr(usize);

impl From<usize> for Paddr {
    fn from(value: usize) -> Self {
        Self(value)
    }
}

impl Add<usize> for Paddr {
    type Output = Paddr;
    fn add(self, rhs: usize) -> Self::Output {
        Paddr::from(self.0 + rhs)
    }
}

impl Sub<usize> for Paddr {
    type Output = Paddr;
    fn sub(self, rhs: usize) -> Self::Output {
        Paddr::from(self.0 - rhs)
    }
}

impl Sub<Paddr> for Paddr {
    type Output = Paddr;
    fn sub(self, rhs: Paddr) -> Self::Output {
        Paddr::from(self.0 - rhs.0)
    }
}

impl Paddr {
    pub const fn to_value(&self) -> usize {
        self.0
    }

    pub fn to_pfn(&self) -> Pfnaddr {
        Pfnaddr::from(self.0 >> page::PAGE_SHIFT)
    }

    pub fn to_pfn_up(&self) -> Pfnaddr {
        Pfnaddr::from((self.0 + page::PAGE_SIZE - 1) >> page::PAGE_SHIFT)
    }

    pub fn to_pfn_down(&self) -> Pfnaddr {
        Pfnaddr::from(self.0 >> page::PAGE_SHIFT)
    }
}
